#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "sniffer.h"
#include "packge_handler.h"
#include<QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    this->setWindowState(Qt::WindowMaximized);
    sniffer = new Sniffer();

    ui->setupUi(this);

    ui->stopButton->setDisabled(true);
    show_state("welcome");
    show_all_devices();

    //初始化过滤字符串
    this->filter = "";

    //绑定事件
    connect(sniffer,&Sniffer::packge_signal,this,&MainWindow::get_packge);

    connect(ui->tableView, SIGNAL(clicked(const QModelIndex &)), this, SLOT(tableView_cellClicked(const QModelIndex &)));


    //初始化table
    this->model = new QStandardItemModel;
    ui->tableView->setModel(model);
    //设置不可编辑
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    // 设置选中为整行选中
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    //隐藏行号
    ui->tableView->verticalHeader()->setHidden(true);
    ui->treeWidget->setHeaderHidden(true);

    this->model->setHorizontalHeaderItem(0, new QStandardItem("No.") );
    this->model->setHorizontalHeaderItem(1, new QStandardItem("Time") );
    this->model->setHorizontalHeaderItem(2, new QStandardItem("Source") );
    this->model->setHorizontalHeaderItem(3, new QStandardItem("Destication") );
    this->model->setHorizontalHeaderItem(4, new QStandardItem("Protocol") );
    this->model->setHorizontalHeaderItem(5, new QStandardItem("Length") );
    this->model->setHorizontalHeaderItem(6, new QStandardItem("Info") );

    ui->tableView->setColumnWidth(0,50);
    ui->tableView->setColumnWidth(1,100);
    ui->tableView->setColumnWidth(2,150);
    ui->tableView->setColumnWidth(3,150);
    ui->tableView->setColumnWidth(4,100);
    ui->tableView->setColumnWidth(5,100);
    ui->tableView->setColumnWidth(6,1000);

}

MainWindow::~MainWindow()
{
    pcap_freealldevs(all_devices);
    delete ui;
}


//显示所有的网络设备
void MainWindow::show_all_devices()
{
    if(pcap_findalldevs_ex(PCAP_SRC_IF_STRING,
                           NULL /* auth is not needed */,
                           &all_devices, errbuf)==-1){
        show_state(errbuf);
        return;
    }
    ui->comboBox->clear();

    for(d=all_devices;d;d=d->next){
        QString name = d->name;
        name.replace("rpcap://\\Device\\","");
        QString des = d->description;
        des.replace("Network adapter '","");
        des.replace("' on local host","");
        ui->comboBox->addItem(des);
    }
}

//显示下方的状态栏
void MainWindow::show_state(QString state)
{
    ui->statusbar->showMessage(state);
}

void MainWindow::on_comboBox_currentIndexChanged(int index)
{
    qDebug("当前%d号网卡",index);
    int i=0;
    //找到链表中第index号设备
    for(d=all_devices,i=0;i<index-1;d=d->next,i++);

    pcap_t *adhandle;
    /* Open the device */
    if ( (adhandle= pcap_open(d->name, // name of the device
          65536, // portion of the packet to capture.
                 // 65536 guarantees that the whole packet will
                 // be captured on all the link layers
          PCAP_OPENFLAG_PROMISCUOUS, // promiscuous mode
          1000, // read timeout
          NULL, // authentication on the remote machine
          errbuf // error buffer
      ) ) == NULL)
    {
      qDebug("\nUnable to open the adapter. %s is not supported by Npcap\n",
        d->name);
      /* Free the device list */
      pcap_freealldevs(all_devices);
      return ;
    }

    sniffer->set_adhandle(adhandle);
    sniffer->start();

    //重新应用捕获过滤器
    this->on_lineEdit_returnPressed();
}

//处理报文数据
void MainWindow::get_packge(const unsigned char* content,struct pcap_pkthdr * header)
{
    struct tm ltime;
    char timestr[16];
    time_t local_tv_sec;

    /*时间格式转化 */
    local_tv_sec = header->ts.tv_sec;
    localtime_s(&ltime, &local_tv_sec);
    strftime( timestr, sizeof timestr, "%H:%M:%S", &ltime);


    my_packge* pack = eth_handler(content);
    if(pack->isHidden) return;

    QList<QStandardItem*> add_items;
    add_items << new QStandardItem(QString::number(model->rowCount()+1));
    add_items << new QStandardItem(timestr);
    add_items << new QStandardItem(pack->source);
    add_items << new QStandardItem(pack->destination);
    add_items << new QStandardItem(pack->proto);
    add_items << new QStandardItem(QString::number(header->len));
    add_items << new QStandardItem(pack->info);

    this->model->appendRow(add_items);

    this->packges.append(content);

    //显示过滤
    if(!this->filter.isEmpty() && QString::compare(this->filter,pack->proto)!= 0){
        this->ui->tableView->setRowHidden(model->rowCount()-1,true);
    }
}

void MainWindow::on_deleteButton_clicked()
{
    for (int i = 0; i< this->packges.size(); ++i)
    {
        delete this->packges[i];
        this->packges[i] = nullptr;
    }
    this->packges.clear();

    this->model->removeRows(0,this->model->rowCount());

    this->ui->treeWidget->clear();
}

void MainWindow::on_startButton_clicked()
{
    ui->startButton->setDisabled(true);
    ui->stopButton->setDisabled(false);
    this->sniffer->start_sniffer();

    QString show = "正在捕获";
    if(!this->capture_filter.isEmpty()){
        show+=",当前捕获过滤器:"+this->capture_filter;
    }
    show_state(show);
}

void MainWindow::on_stopButton_clicked()
{
    ui->startButton->setDisabled(false);
    ui->stopButton->setDisabled(true);
    this->sniffer->pause_sniffer();
    show_state("");
}

//过滤应用包
void MainWindow::on_textEdit_returnPressed()
{
    this->filter = ui->textEdit->text().toUpper();
    int count = this->model->rowCount();
    for(int i=0;i<count;i++){
        QString proto = model->item(i,4)->text();
        if(QString::compare(proto,this->filter)!=0&&!this->filter.isEmpty()){
            this->ui->tableView->setRowHidden(i,true);
        }else{
            this->ui->tableView->setRowHidden(i,false);
        }
    }
}

//应用捕获过滤器
void MainWindow::on_lineEdit_returnPressed()
{
    QString temp_capture_filter = this->ui->lineEdit->text();
    const char * filter = temp_capture_filter.toStdString().c_str();

    u_int netmask = 0xffffff;
    struct bpf_program fcode;

    //compile the filter
    if (pcap_compile(sniffer->get_adhandle(), &fcode, filter, 1, netmask) < 0)
    {
      this->on_stopButton_clicked();
      show_state("Unable to compile the packet filter. Check the syntax.");
      return;
    }

    //set the filter
    if (pcap_setfilter(sniffer->get_adhandle(), &fcode) < 0)
    {
      this->on_stopButton_clicked();
      show_state("Error setting the filter.");
      return ;
    }

    this->capture_filter = temp_capture_filter;
    if(this->ui->stopButton->isEnabled() && !this->capture_filter.isEmpty()){
        show_state("正在捕获，当前捕获过滤器:"+this->capture_filter);
    }
}

//选中数据
void MainWindow::tableView_cellClicked(const QModelIndex &index)
{
    this->ui->treeWidget->clear();
    int row = index.row();
    delete eth_handler(this->packges[row],this->ui);

}


